package xm.components.table
{
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.Sprite;
	import flash.utils.getDefinitionByName;
	
	import xm.LivePreviewTester;
	import xm.align.AlignFactory;
	import xm.components.checkbox.CheckBox;
	import xm.core.XMSprite;
	import xm.debug.DEBUG_LivePreview;
	import xm.debug.log;
	import xm.definition.Align;
	import xm.definition.Arrange;
	
	/**
	 * <br> 클래스 설명 : </br>
	 * @author 김정환
	 */	
	public class TD extends Sprite
	{
		
		//-----------------------------------------------------------------------------------
		// public vars
		//-----------------------------------------------------------------------------------
		
//		/**
//		 * x : Number - table로부터 논리적인 x 상대좌표.  
//		 */		
//		public var x : Number = 0;
//		
//		/**
//		 * y : Number - table로부터 논리적인 y 상대좌표.  
//		 */		
//		public var y : Number = 0;
//		
//		/**
//		 * width : Number - 논리적인 width값.  
//		 */		
//		public var width : Number = 0;
//		
//		/**
//		 * height : Number - 논리적인 height값.  
//		 */		
//		public var height : Number = 0;
		
		
		
		/**
		 * 부모 parent 객체. 
		 */		
		public var parentTable : Table;
		
		/** 보더 - 좌측 색상 **/
		public var borderLeftColor : uint = 0xffffff;
		
		/** 보더 - 좌측 알파 **/
		public var borderLeftAlpha : Number = 1;
		
		/** 보더 - 좌측 두께 **/
		public var borderLeftThickness : Number = 0;
		
		
		/** 배경색상 **/
		public var backgroundColor : uint = 0xffffff;
		
		/** 배경알파 **/
		public var backgroundAlpha : Number = 0;
		
		
		
		/**
		 *  paddingTop
		 */		
		public var paddingTop : Number = 0;
		
		/**
		 *  paddingRight
		 */		
		public var paddingRight : Number = 0;
		
		/**
		 *  paddingBottom
		 */		
		public var paddingBottom : Number = 0;
		
		/**
		 * paddingLeft 
		 */		
		public var paddingLeft : Number = 0;
		
		
		/**
		 * 정렬타입 ( default = Arrange.VERTICAL ), Arrange.HORIZONTAL<br />
		 */		
		public var arrangeType : String = "vertical";
		
		/**
		 * displayObject 들 사이의 gap
		 */		
		public var gapBetweenChild : Number = 0;
		
		
		/**
		 * 정렬 방법 ( default : Align.TOP )
		 */		
		public var alignVertical : String = "top";
		
		/**
		 * 정렬 방법 ( default : Align.LEFT )
		 */		
		public var alignHorizontal : String = "left";
		
		
		//-----------------------------------------------------------------------------------
		// protected / internal vars
		//-----------------------------------------------------------------------------------
		
		
		
		
		//-----------------------------------------------------------------------------------
		// private vars
		//-----------------------------------------------------------------------------------
		
		
		private var _af : AlignFactory = new AlignFactory();
		private var _childList : Array = [];
		private var _fitWidthList : Array = [];
		private var _fitHeightList : Array = [];
		
		
		private var _maxWidth : Number = 0;
		private var _maxHeight : Number = 0;
		
		private var _livePreviewParentTR : DisplayObject;
		
		//-----------------------------------------------------------------------------------
		// public functions
		//-----------------------------------------------------------------------------------
		
		/**
		 * constructor 
		 */	
		public function TD()
		{
			
		}
		
		
		
		/**
		 * commitProperties
		 */		
		public function commitProperties():void
		{
			
		}
		
		
		
		/**
		 * updateDisplayList
		 */		
		public function updateDisplayList():void
		{
			var i:int = 0,
				len:int = _childList.length,
				sum : Number = 0,
				extraX : Number = 0,
				extraY : Number = 0,
				innerPaddingTop : Number = 0,
				innerPaddingLeft : Number = 0;
			
			if( len == 0 ) return;
			
			_af.destroy();
			_af.setAlignFactory(len,null,arrangeType);
			
			
			// 1. 정렬방법이 세로로 가운데 정렬이면
			if( alignVertical == Align.MIDDLE )
			{
				sum = getSumChildHeightAndGap();
				extraY = ( height - sum ) / 2;
			}
			// 또는 아래 정렬이면,
			else if( alignVertical == Align.BOTTOM )
			{
				sum = getSumChildHeightAndGap();
				extraY = ( height - sum ) - paddingBottom;
			}
			
			// 2. 정렬방법이 가로로 가운데 정렬이면,
			if( alignHorizontal == Align.CENTER )
			{
				sum = getSumChildWidthAndGap();
				extraX = ( width - sum ) /2;
			}
			else if( alignHorizontal == Align.RIGHT )
			{
				sum = getSumChildWidthAndGap();
				extraX = ( width - sum ) - paddingRight;
			}
			
			
			// 기본 x, y 좌표를 정의하고,
			_af.setPosition( x+1+paddingLeft+extraX, y+1+paddingTop+extraY );
			
			
			// 정렬 시작.
			i = 0;
			while( i<len )
			{
				if( parent && parent.contains( _childList[ i ] ) == false ) parent.addChild( _childList[ i ] as DisplayObject );
				
				// i != 0 일때만 top padding 으로 gap 을 적용함.
				if( arrangeType == Arrange.VERTICAL )
				{
					innerPaddingTop = ( (i==0)?0:gapBetweenChild );
					
					switch( alignHorizontal )
					{
					case Align.LEFT : 
						innerPaddingLeft = 0;
						break;
					case Align.CENTER : 
						innerPaddingLeft = ( ( _maxWidth-_childList[ i ].width )/2 );
						break;
					case Align.RIGHT : 
						innerPaddingLeft = ( _maxWidth-_childList[ i ].width );
						break;
					}
					
					_af.addSimpleItem( _childList[ i ] , [ innerPaddingTop, 0, 0, innerPaddingLeft] );
				}
				else
				{
					innerPaddingLeft = ( (i==0)?0:gapBetweenChild );
					
					switch( alignVertical )
					{
						case Align.TOP : 
							innerPaddingTop = 0;
							break;
						case Align.MIDDLE : 
							innerPaddingTop = ( ( _maxHeight-_childList[ i ].height )/2 );
							break;
						case Align.BOTTOM : 
							innerPaddingTop = ( _maxHeight-_childList[ i ].height );
							break;
					}
					
					_af.addSimpleItem( _childList[ i ] , [ innerPaddingTop, 0, 0, innerPaddingLeft] );
				}
				++i;
			}
			
			
			
			_af.workingAlign();
			// 정렬 끝
			
			
			
			
			
			
			// 너비 fit 인것들 처리.
			i=0;
			len=_fitWidthList.length;
			
			while( i<len )
			{
				_fitWidthList[ i ].width = width-paddingLeft-paddingRight;
				++i;
			}
			
			// 높이 fit 인것들 처리.
			i=0;
			len=_fitHeightList.length;
			
			while( i<len )
			{
				_fitHeightList[ i ].height = height-paddingTop-paddingBottom;
				++i;
			}
			
		}
		
		
		/**
		 * @param child : DisplayObject;
		 */		
		public function addChildToTable( child:DisplayObject, fitWidth : Boolean = false, fitHeight : Boolean = false ):void
		{
			_childList.push( child );
			if( parent ) parent.addChild( parent );
			
			if( fitWidth ) _fitWidthList.push( child );
			if( fitHeight ) _fitHeightList.push( child );
		}
		
		
		/**
		 * @param child : DisplayObject;
		 */		
		public function addChildAtToTable( child:DisplayObject, index:int, fitWidth : Boolean = false, fitHeight : Boolean = false ):void
		{
			if( _childList.length > index )
			{
				_childList.splice( index, 0 , child );
			}
			else
			{
				throw new Error( "TD - addChildAt : index가 자식의 갯수를 초과했습니다." );
				return;
			}
			
			if( parent ) parent.addChild( parent );
			
			if( fitWidth ) _fitWidthList.push( child );
			if( fitHeight ) _fitHeightList.push( child );
		}
		
		/**
		 * @param child
		 */		
		public function removeChildFromTable( child:DisplayObject ):void
		{
			var idx : int = _childList.indexOf( child );
			
			if( idx > -1 ) _childList.splice( idx, 1 );
			else 
			{
				throw new Error( "TD - removeChild : child가 해당 TD의 자식이 아닙니다." );
				return;
			}
			
			idx = _fitWidthList.indexOf( child );
			if( idx > -1 ) _fitWidthList.splice( idx, 1 );
			idx = _fitHeightList.indexOf( child );
			if( idx > -1 ) _fitHeightList.splice( idx, 1 );
			
			if( parent.contains( child ) ) parent.removeChild( child );
		}
		
		
		/**
		 * @param index
		 */		
		public function removeChildAtFromTable( index : int ):void
		{
			if( _childList.length > index )
			{
				var child : DisplayObject = _childList[ index ],
					idx : int = 0;
				
				_childList.splice( index, 1 );
				
				idx = _fitWidthList.indexOf( child );
				if( idx > -1 ) _fitWidthList.splice( idx, 1 );
				idx = _fitHeightList.indexOf( child );
				if( idx > -1 ) _fitHeightList.splice( idx, 1 );
				
			}
			else
			{
				throw new Error( "TD - removeChildAt : index가 자식의 갯수를 초과했습니다." );
				return;
			}
		}
		
		
		
		
		[Inspectable(name="setParentTR", defaultValue = "", type = String )]
		public function set setParentTR( pTR : String ):void
		{
			if( LivePreviewTester.isLive( this ) == true )
			{
				var list : Array, i:int, len : int;
				
				DEBUG_LivePreview.setStageAndSize( this, 500, 700 );
				list = LivePreviewTester.getDisObjListFromStage( this );
				
				i=0;
				len = list.length;
				while( i<len )
				{
					log(len, i ,( list[ i ] as DisplayObject ).hitTestObject( this ), ( list[ i ] == this ) );
					
					if( ( list[ i ] as DisplayObject ).hitTestObject( this ) == true && ( list[ i ] != this ) )
					{
						_livePreviewParentTR = list[ i ] as DisplayObject;
					}
					
					++i;
				}
			}
			
		}
		
		
		
		//-----------------------------------------------------------------------------------
		// life cycle functions
		//-----------------------------------------------------------------------------------
		
		
		/**
		 * destroy
		 */		
		public function destroy():void
		{
			var i:int, len:int;
			
			// 속성제거.
			x = NaN;
			y = NaN;
			
			width = NaN;
			height = NaN;
			
			borderLeftColor = 0;
			borderLeftAlpha = NaN;
			borderLeftThickness = NaN;
			
			backgroundColor = 0;
			backgroundAlpha = NaN;
			
			padding = [NaN,NaN,NaN,NaN];
			arrangeType = null;
			gapBetweenChild = NaN;
			alignVertical = null;
			alignHorizontal = null;
			
			if( _af ) _af.destroy();
			_af = null;
			
			_maxWidth = NaN;
			_maxHeight = NaN;
			
			
			// 자식제거
			i=0;
			len=_childList.length;
			while( i<len )
			{
				if( _childList[ i ] is XMSprite )
				{
					( _childList[ i ] as XMSprite ).destroy();
				}
				
				if( parent.contains( _childList[ i ] as DisplayObject ) )
				{
					parent.removeChild( _childList[ i ] as DisplayObject );
				}
				
				delete _childList[ i ];
				++i;
			}
			_childList = null;
			
			
			// 너비, 높이 고정컨텐츠 리스트 제거.
			i=0;
			len=_fitWidthList.length;
			while( i<len )
			{
				delete _fitWidthList[ i ];
				++i;
			}
			_fitWidthList = null;
			
			
			i=0;
			len=_fitHeightList.length;
			while( i<len )
			{
				delete _fitHeightList[ i ];
				++i;
			}
			_fitHeightList = null;
			
			
			// 부모 제거.
			parentTable = null;
		}
		
		//-----------------------------------------------------------------------------------
		// setter / getter
		//-----------------------------------------------------------------------------------
		
		
		/**
		 * <br>패딩값 default : 0,0,0,0</br>
		 * <br> - 시계방향으로 위, 오른쪽, 아래, 왼쪽 순서임 </br> 
		 */
		public function get padding():Array
		{
			return [paddingTop, paddingRight, paddingBottom, paddingLeft];
		}
		
		/**
		 * @private : Array - 상, 우, 하, 좌 ( 시게방향 )
		 */
		public function set padding(value:Array):void
		{
			if( value == null ) value = [0,0,0,0];
			
			paddingTop = value[ 0 ];
			paddingRight = value[ 1 ];
			paddingBottom = value[ 2 ];
			paddingLeft = value[ 3 ];
		}
		
		
//		public function set setAlignHorizontal( _alignHorizontal : String ):void
//		{
//			alignHorizontal = _alignHorizontal;
//		}
		
		//-----------------------------------------------------------------------------------
		// protected functions
		//-----------------------------------------------------------------------------------
		
		
		
		//-----------------------------------------------------------------------------------
		// internal functions
		//-----------------------------------------------------------------------------------
		
		
		
		
		//-----------------------------------------------------------------------------------
		// private functions
		//-----------------------------------------------------------------------------------
		
		
		private function getSumChildHeightAndGap():Number
		{
			var i:int=0,
				len:int=_childList.length,
				sum:Number=0;
			
			while( i<len )
			{
				if( arrangeType == Arrange.VERTICAL )
				{
					sum += _childList[ i ].height + gapBetweenChild;
				}
				else
				{
					sum = Math.max( sum , _childList[ i ].height );
				}
				
				_maxHeight = Math.max( _maxHeight, _childList[ i ].height );
				
				++i;
			}
			
			if( arrangeType == Arrange.VERTICAL )
			{
				sum -= gapBetweenChild;
			}
			
			return sum;
		}
		
		private function getSumChildWidthAndGap():Number
		{
			var i:int=0,
				len:int=_childList.length,
				sum:Number=0;
			
			while( i<len )
			{
				if( arrangeType == Arrange.HORIZONTAL )
				{
					sum += _childList[ i ].width + gapBetweenChild;
				}
				else
				{
					sum = Math.max( sum , _childList[ i ].width );
				}
				
				_maxWidth = Math.max( _maxWidth, _childList[ i ].width );
				
				++i;
			}
			
			if( arrangeType == Arrange.HORIZONTAL )
			{
				sum -= gapBetweenChild;
			}
			
			return sum;
		}
		
		//-----------------------------------------------------------------------------------
		// event handler
		//-----------------------------------------------------------------------------------
		
		
		
		
		
		
		
		
		
	}
}